#include <ArduinoWebsockets.h>
#include <WiFi.h>
#include <TJpg_Decoder.h>
#include <TFT_eSPI.h>

TFT_eSPI tft = TFT_eSPI();
TFT_eSprite clk = TFT_eSprite(&tft);

const char *ssid = "leisure";
const char *password = "shadow27";

using namespace websockets;
WebsocketsServer server;
WebsocketsClient client;

#define BLK 11 // 亮度控制

const int fillcol = 0x0F0F;  // 进度条填充颜色，绿色
const int lightcol = 0xffff; // 白色
const int darkcol = 0x0000;  // 黑色

uint8_t loadNum = 6; // 开机启动进度条的起始位置

// 开机联网动画
void PowerOn_Loading(uint8_t delayTime) // 开机联网显示的进度条，输入延时时间
{
  clk.setColorDepth(8);      // 颜色位深，可显示256(2的8次方)种颜色
  clk.createSprite(200, 50); // 创建画布Sprite
  clk.fillSprite(darkcol);   // 画布填充颜色
  // clk.loadFont(FxLED_32); // 导入字体库

  clk.drawRoundRect(0, 0, 200, 16, 8, 0xFFFF);      // 画一个圆角矩形，白色边框
  clk.fillRoundRect(3, 3, loadNum, 10, 5, fillcol); // 画一个填充的圆角矩形

  clk.setTextDatum(CC_DATUM);                          // 设置对齐方式，
  clk.setTextColor(lightcol, darkcol);                 // 文本的前景色和背景色
  clk.drawString("Connecting to WiFi...", 100, 40, 2); // 显示文本

  clk.pushSprite(20, 110);

  clk.deleteSprite(); // 删除Sprite，释放RAM资源
  clk.unloadFont();   // 释放字体库文件，节省资源

  loadNum += 1; // 进度条位置变化，直到加载完成
  if (loadNum >= 194)
  {
    loadNum = 194;
  }
  delay(delayTime);
}

void ConnectWifi()
{
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    for (uint8_t n = 0; n < 10; n++)
    {
      PowerOn_Loading(50); // 每500毫秒检测一次状态
    }
  }
  while (loadNum < 194)
  {                     // 让动画走完
    PowerOn_Loading(1); // 加载动画，加载完后串口输出wifi信息
  }

  Serial.println(F(""));
  Serial.println(F("WiFi Connected!"));
  Serial.print("IP:");
  Serial.println(WiFi.localIP());
}

// 解码JPEG并显示
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t *bitmap)
{
  if (y >= tft.height())
    return 0;
  tft.pushImage(x, y, w, h, bitmap);
  return 1;
}

void TFT_init()
{
  pinMode(BLK, OUTPUT);
  analogWrite(BLK, 250);

  tft.begin();
  tft.setRotation(1);
  tft.setSwapBytes(true);          // We need to swap the colour bytes (endianess)
  TJpgDec.setJpgScale(1);          // The jpeg image can be scaled by a factor of 1, 2, 4, or 8
  TJpgDec.setCallback(tft_output); // 图片解码
  tft.fillScreen(darkcol);         // 清屏
}

void Websocket(void *pt)
{
  ConnectWifi();
  server.listen(8888);
  while (1)
  {
    if (server.poll()) // 检测是否有数据可读取
    {
      client = server.accept();
    }

    if (client.available())
    {
      client.poll();
      WebsocketsMessage msg = client.readBlocking(); // 接收数据

      uint32_t t = millis();
      TJpgDec.drawJpg(0, 0, (const uint8_t *)msg.c_str(), msg.length()); // Draw the image, top left at 0,0

      t = millis() - t; // 测试输出渲染时间
      Serial.print(t);
      Serial.println(" ms");
      taskYIELD();
    }
  }
}

void setup()
{
  Serial.begin(115200);
  TFT_init();

  xTaskCreatePinnedToCore(Websocket, "", 1024 * 5, NULL, 2, NULL, 1);
}

void loop()
{
}